﻿using Aspose.Cells;
using BillUpload.Model;
using BillUpload.Util;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BillUpload
{
    public partial class Form1 : Form
    {
        //需要处理的门店编号
        private List<String> platShopIds = new List<string>();
        public DataTable MeiTuanBillSource { get; private set; }
        public DataTable MeiTuanBillDetailSource { get; private set; }
        private readonly String ServerUrl = ConfigurationManager.AppSettings["ServerUrl"];
        private readonly String Merchant = ConfigurationManager.AppSettings["Merchant"];
        private readonly String MeiTuanAppId = ConfigurationManager.AppSettings["MeiTuanAppId"];

        private Stopwatch readStopwatch = new Stopwatch();
        private Stopwatch uploadStopwatch = new Stopwatch();

        public Form1()
        {
            InitializeComponent();
            this.Text = "账单手动导入 V1.6";
            this.CenterToScreen();
            this.MaximizeBox = false;

            if (String.IsNullOrWhiteSpace(ServerUrl) || String.IsNullOrWhiteSpace(Merchant) || String.IsNullOrWhiteSpace(MeiTuanAppId))
            {
                MessageBox.Show("启动失败,请检查配置.");
                Environment.Exit(0);
            }
            if (!"syyz".Equals(Merchant) && !"xtsy".Equals(Merchant))
            {
                MessageBox.Show("启动失败,非法商户.");
                Environment.Exit(0);
            }
        }

        #region 按钮事件
        /// <summary>
        /// 抖音Json数据上传
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DouYinJsonBut_Click(object sender, EventArgs e)
        {
            DouYinJsonBut.Enabled = false;
            String platMark = "douyin";
            MessageBox.Show("此功能只能解析一家门店的JSON处理好的格式,并且是数组类型的JSON文件.");
            string textFilePath = GetSelectPath("支持的文件|*.json;*.txt|Json文件|*.json|Text文件|*.txt");
            if (textFilePath != "")
            {
                //1.判断文件大小
                long fileSize = new FileInfo(textFilePath).Length;
                if (fileSize < 10)
                {
                    MessageBox.Show("上传的JSON文件貌似是空文件.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    DouYinJsonBut.Enabled = true;
                    return;
                }
                if (fileSize > 5242880)
                {
                    MessageBox.Show("上传的JSON文件不能大于5MB.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    DouYinJsonBut.Enabled = true;
                    return;
                }

                //2.解析Json内容
                string strContent = File.ReadAllText(textFilePath);
                List<BillDetail> billDetails = JsonUtil.FromJSON<List<BillDetail>>(strContent);
                if (null == billDetails || billDetails.Count == 0)
                {
                    MessageBox.Show("解析Json文件失败.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    DouYinJsonBut.Enabled = true;
                    return;
                }

                //3.组装数据                
                BillDetail tempDetail = billDetails[0];
                Bill bill = new Bill
                {
                    id = tempDetail.billId,
                    platShopId = tempDetail.platShopId,
                    billDate = tempDetail.billDate,
                    checkoutDate = tempDetail.checkoutDate,
                    checkoutAmount = Math.Round(billDetails.Sum(x => x.checkoutAmount), 2),
                    transferAmount = Math.Round(billDetails.Sum(x => x.finalAmount), 2),
                    status = 2,
                    verifyCheckout = 1,
                    verifyTransfer = 1,
                    createId = Merchant
                };

                //4.验证并提交数据     
                uploadStopwatch.Restart();
                List<Bill> billList = new List<Bill>() { bill };
                ErpResult erpResult = VerifyDate(billList, billDetails, platMark);
                uploadStopwatch.Stop();
                double uploadWait = Math.Round(uploadStopwatch.Elapsed.TotalSeconds, 2);
                DouYinJsonBut.Text = "共[" + billList.Count + "]条汇总,[" + billDetails.Count + "]条明细\n上传耗时[" + uploadWait + "]秒";
                DouYinJsonBut.Enabled = true;
            }
        }


        /// <summary>
        /// 美团Excel数据源上传
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MeiTuanSourceBut_Click(object sender, EventArgs e)
        {
            string excelFilePath = GetSelectPath("支持的文件|*.xls;*.xlsx|高版本Excel文件|*.xlsx|低版本Excel文件|*.xls");
            if (excelFilePath != "")
            {
                String platMark = "meituan";
                Dictionary<String, String> param = new Dictionary<string, string>() {
                    { "platMark",platMark},{ "merchant",Merchant}
                };

                ErpResult erpResult = HttpUtil.GetPlatShopList(ServerUrl + "/OrderTaking/bill/getBillShopId", JsonUtil.ToJSON(param));
                //Console.WriteLine(erpResult);
                if (null != erpResult)
                {
                    if (erpResult.success)
                    {
                        platShopIds = JsonUtil.FromJSON<List<String>>(JsonUtil.ToJSON(erpResult.data));
                        if (platShopIds.Count <= 0)
                        {
                            MessageBox.Show("未获取到远程平台店铺编号.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        else
                        {
                            ReadExcelFile((Button)sender, excelFilePath, platMark);
                        }
                    }
                    else
                    {
                        MessageBox.Show(erpResult.message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        /// <summary>
        /// 添加美团门店
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MeiTuanAddShopBut_Click(object sender, EventArgs e)
        {
            this.MeiTuanAddShopBut.Enabled = false;

            String platShopId = textBoxPlatShopId.Text.Trim();
            String platShopName = textBoxPlatShopName.Text.Trim();
            if (platShopId == "" || platShopName == "")
            {
                MessageBox.Show("店铺编号和店铺名称不能为空.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.MeiTuanAddShopBut.Enabled = true;
            }
            else
            {
                String platMark = "meituan";
                Dictionary<String, String> param = new Dictionary<string, string>() {
                    { "platMark",platMark},{ "merchant",Merchant} ,{ "platShopId",platShopId},{ "platShopName",platShopName},
                    { "appId",MeiTuanAppId}
                };
                ErpResult erpResult = HttpUtil.AddPlatShopList(ServerUrl + "/OrderTaking/bill/addBillShopId", JsonUtil.ToJSON(param));
                if (null != erpResult)
                {
                    if (erpResult.success)
                    {
                        MessageBox.Show(erpResult.message, "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                    {
                        MessageBox.Show(erpResult.message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                this.MeiTuanAddShopBut.Enabled = true;
            }
        }
        #endregion



        #region 公共方法
        /// <summary>
        /// 获取选择文件路径 
        /// </summary>
        /// <returns></returns>
        private string GetSelectPath(String filterType)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = filterType,
                RestoreDirectory = true
            };
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                return openFileDialog.FileName;
            }
            return "";
        }

        /// <summary>
        /// 读取Excel文件
        /// </summary>
        private void ReadExcelFile(Button button, String excelFilePath, String platMark)
        {
            new Task(() =>
            {
                readStopwatch.Restart();
                Workbook workbook = new Workbook(excelFilePath);
                if (workbook.Worksheets["账单明细"] == null)
                {
                    MessageBox.Show("请检查[账单明细]Sheet是否存在.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                if (workbook.Worksheets["订单明细"] == null)
                {
                    MessageBox.Show("请检查[订单明细]Sheet是否存在.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                this.BeginInvoke(new MethodInvoker(() =>
                {
                    button.Text = "正在读取请稍后.";
                    button.Enabled = false;
                }));

                //===1 读取账单汇总===
                Cells billCells = workbook.Worksheets["账单明细"].Cells;
                MeiTuanBillSource = billCells.ExportDataTableAsString(1, 0, billCells.MaxDataRow, billCells.MaxColumn + 1);
                List<Bill> billList = new List<Bill>();

                //填充数据
                int billRowIndex = 0;
                foreach (DataRow row in MeiTuanBillSource.Rows)
                {
                    Bill bill = new Bill();
                    // 遍历所有列
                    foreach (DataColumn col in MeiTuanBillSource.Columns)
                    {
                        if (billRowIndex == 0)
                        {
                            BillUtil.IsReserve(col.ColumnName, row[col].ToString());
                        }
                        else
                        {
                            BillUtil.FillData(bill, col.ColumnName, row[col].ToString());
                        }
                    }
                    if (billRowIndex > 0 && platShopIds.Contains(bill.platShopId))
                    {
                        bill.id = GenerateBillId(platMark, bill.platShopId, bill.checkoutDate);
                        bill.verifyCheckout = 1;
                        bill.verifyTransfer = 1;
                        bill.createId = Merchant;
                        billList.Add(bill);
                    }
                    billRowIndex++;
                }

                //===1 读取账单明细===
                Cells detailCells = workbook.Worksheets["订单明细"].Cells;
                MeiTuanBillDetailSource = detailCells.ExportDataTableAsString(0, 0, detailCells.MaxDataRow + 1, detailCells.MaxColumn + 1);
                List<BillDetail> billDetaillList = new List<BillDetail>();
                //ForDataTable(MeiTuanBillDetailSource, false);
                //填充数据
                int detailRowIndex = 0;
                foreach (DataRow row in MeiTuanBillDetailSource.Rows)
                {
                    BillDetail detail = new BillDetail();
                    // 遍历所有列
                    foreach (DataColumn col in MeiTuanBillDetailSource.Columns)
                    {
                        if (detailRowIndex == 0)
                        {
                            BillDetailUtil.IsReserve(col.ColumnName, row[col].ToString());
                        }
                        else
                        {
                            BillDetailUtil.FillData(detail, col.ColumnName, row[col].ToString());
                        }
                    }

                    if (detailRowIndex > 0 && platShopIds.Contains(detail.platShopId))
                    {
                        detail.billId = GenerateBillId(platMark, detail.platShopId, detail.checkoutDate);
                        if (detail.finalAmount > 0)
                        {
                            detail.detailType = 1;
                        }
                        else
                        {
                            detail.detailType = 10;
                        }
                        //美团返佣订单号处理
                        if (detail.tradeType == "佣金返还"  || detail.tradeType == "餐损赔付" || detail.platOrderId == "-" )
                        {
                            detail.platOrderId = TokenUtil.GetMD5String(detail.billId + detail.detailType);
                        }
                        //美团返佣订单下单时间处理
                        if (detail.createTime == "-")
                        {
                            detail.createTime = detail.billDate + " " + DateTime.Now.ToString("HH:mm:ss");
                        }
                        billDetaillList.Add(detail);
                    }
                    detailRowIndex++;
                }

                readStopwatch.Stop();
                double readWait = Math.Round(readStopwatch.Elapsed.TotalSeconds, 2);

                uploadStopwatch.Restart();
                ErpResult erpResult = VerifyDate(billList, billDetaillList, platMark);
                uploadStopwatch.Stop();
                double uploadWait = Math.Round(uploadStopwatch.Elapsed.TotalSeconds, 2);

                this.BeginInvoke(new MethodInvoker(() =>
                {
                    button.Text = "共[" + billList.Count + "]条汇总,[" + billDetaillList.Count + "]条明细\n处理耗时[" + readWait + "]秒\n上传耗时[" + uploadWait + "]秒";
                    button.Enabled = true;
                }));

                //删除数据源
                MeiTuanBillSource.Clear();
                MeiTuanBillDetailSource.Clear();

                if (erpResult.success)
                {
                    MessageBox.Show(erpResult.message, "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);

                }
                else
                {
                    MessageBox.Show(erpResult.message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }).Start();
        }


        /// <summary>
        /// 遍历输出DataTable
        /// </summary>
        private void ForDataTable(DataTable dt, bool viewColumnName = true)
        {
            //遍历所有行
            foreach (DataRow row in dt.Rows)
            {
                // 遍历所有列
                foreach (DataColumn col in dt.Columns)
                {
                    object value = row[col];
                    Console.Write(viewColumnName ? $"{ col.ColumnName}: {value} " : $"{value},");
                }
                Console.WriteLine("  ");
            }
        }


        /// <summary>
        /// 生成账单编号
        /// </summary>
        /// <param name="platMark"></param>
        /// <param name="platShopId"></param>
        /// <param name="checkoutDate"></param>
        /// <returns></returns>
        public static String GenerateBillId(String platMark, String platShopId, String checkoutDate)
        {
            return TokenUtil.GetMD5String(platMark + platShopId + checkoutDate);
        }

        /// <summary>
        /// 处理并校验数据
        /// </summary>
        /// <param name="_billList"></param>
        /// <param name="_billDetaillList"></param>
        /// <returns></returns>
        private ErpResult VerifyDate(List<Bill> _billList, List<BillDetail> _billDetaillList, String platMark)
        {
            List<Bill> billList = _billList.Where(bill => bill.checkoutAmount != 0).ToList();//最终提交时过滤汇总账单金额为0的门店
            List<BillDetail> billDetails = new List<BillDetail>();//保存后面处理的最终明细账单列表

            //循环处理主账单(账单金额大于0的)
            billList.Where(bill => bill.checkoutAmount != 0).ToList().ForEach(bill =>
              {
                  //根据账单汇总找到对应的账单明细List
                  List<BillDetail> sourceList = _billDetaillList.Where(detail => detail.billId.Equals(bill.id)).ToList();

                  //将一样的订单号的数据合并为一条数据   
                  List<BillDetail> uniquelList = sourceList.GroupBy(detail => detail.platOrderId).Select(group => new BillDetail
                  {
                      platOrderId = group.First().platOrderId,
                      platShopId = group.First().platShopId,
                      billId = group.First().billId,
                      billDate = group.First().billDate,
                      checkoutDate = group.First().checkoutDate,
                      daySn = group.First().daySn,
                      detailType = group.Sum(detail => Math.Round(detail.checkoutAmount, 2)) > 0 ? 1 : 10,
                      checkoutAmount = group.Sum(detail => Math.Round(detail.checkoutAmount, 2)),
                      finalAmount = group.Sum(detail => Math.Round(detail.finalAmount, 2)),
                      createTime = group.First().createTime,
                      finishTime = group.First().finishTime,
                      accountId = group.First().accountId
                  }).ToList();

                  //取出最终大于0的明细
                  List<BillDetail> finallList = uniquelList.Where(detail => detail.checkoutAmount > 0).ToList();

                  //过滤处小于0的记录
                  List<BillDetail> tempList = uniquelList.Where(detail => detail.checkoutAmount < 0).ToList();
                  if (tempList.Count > 0)
                  {
                      //将第一条负金额的数据进行复制
                      BillDetail tempDetail = tempList[0];
                      BillDetail costetail = JsonUtil.FromJSON<BillDetail>(JsonUtil.ToJSON(tempDetail));
                      costetail.platOrderId = TokenUtil.GetMD5String(tempDetail.billId + tempDetail.detailType);
                      costetail.checkoutAmount = (tempList.Sum(x => Math.Round(x.checkoutAmount, 2)));
                      costetail.finalAmount = costetail.checkoutAmount;
                      costetail.daySn = -1;
                      if (costetail.createTime == "-")
                      {
                          costetail.createTime = costetail.finishTime;
                      }
                      finallList.Add(costetail);
                  }
                  if (bill.checkoutAmount != Math.Round(finallList.Sum(x => x.checkoutAmount), 2))
                  {
                      String errMsg = bill.platShopName + "[" + bill.platShopId + "],汇总金额:" + bill.checkoutAmount + ",明细金额:" + finallList.Sum(x => x.checkoutAmount);
                      MessageBox.Show(errMsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                      throw new Exception(errMsg);
                  }
                  else
                  {
                      billDetails.AddRange(finallList);
                  }
              });
            Dictionary<String, Object> requestParam = new Dictionary<string, object>
                {
                    { "bill", billList },
                    { "detail", billDetails },
                    { "platMark",platMark}
                };
            if (billList.Count == 0)
            {
                MessageBox.Show("没有可上传的账单数据.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw new Exception("没有可上传的账单数据.");
            }
            else
            {
                return HttpUtil.PutBill(ServerUrl + "/OrderTaking/bill/uploadBill", JsonUtil.ToJSON(requestParam));
            }
        }
        #endregion
    }
}